package com.hotel.hotelsystem.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.common.status.ResultMsg;
import com.common.status.StatusCode;
import com.common.utils.ResultUtils;
import com.common.utils.ResultVo;
import com.hotel.customersystem.pojo.CustomerUser;
import com.hotel.customersystem.service.CustomerUserService;
import com.hotel.hotelsystem.mapper.HotelInfoMapper;
import com.hotel.hotelsystem.mapper.RoomInfoMapper;
import com.hotel.hotelsystem.mapper.RoomListMapper;
import com.hotel.hotelsystem.mapper.RoomMapper;
import com.hotel.hotelsystem.pojo.HotelInfo;
import com.hotel.hotelsystem.pojo.Room;
import com.hotel.hotelsystem.pojo.RoomInfo;
import com.hotel.hotelsystem.pojo.RoomList;
import com.hotel.hotelsystem.service.RoomInfoService;
import com.hotel.hotelsystem.service.RoomListService;
import com.hotel.ordersystem.pojo.CommentMongoDB;
import com.hotel.websocketsystem.pojo.Customer;
import com.mongodb.client.result.UpdateResult;
import io.swagger.models.auth.In;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

/**
 * (RoomList)表服务实现类
 *
 * @author makejava
 * @since 2022-09-30 18:23:54
 */
@Service("roomListService")
public class RoomListServiceImpl implements RoomListService {

    @Autowired
    private RoomListMapper roomListMapper;

    @Autowired
    private RoomInfoMapper roomInfoMapper;

    @Autowired
    private RoomMapper roomMapper;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private CustomerUserService customerUserService;

    /**
     * 查询当前酒店所有剩余房间信息
     * 1.查询 room_info 表 条件: 酒店id 入住时间  查询: 房间编号 (查询出的房间编号 封装成list)
     * 2.查询 room 表 条件: 酒店id room_info当中查询出的房间编号依次查询 (roomList封装 房间类型id(存在重复情况))
     * 3.对 roomList 进行房间类型的统计 封装成 Map(房间类型id,房间数量)
     * 4.根据查询出来的房间类型id 修改 room_left_num 的剩余房间数量
     * 5.根据酒店id查询 room_list 并封装完成返回给前端
     * @param hotelId
     * @return
     */
    @Override
    public List<RoomList> selectHotelToRoomList(int hotelId) {
        //1.查询 room_info 表 条件: 酒店id 入住时间  查询: 房间编号 (查询出的房间编号 封装成list)
        LocalDateTime today = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
//        System.out.println("今日: "+today);
        QueryWrapper<RoomInfo> qw = new QueryWrapper<>();
        qw.ge("in_time",today);
        qw.eq("hotel_id",hotelId);
        qw.select("room_num");
        List<RoomInfo> roomInfoList = roomInfoMapper.selectList(qw);
        List<Object> listRoomNum = new ArrayList<>();
        for (RoomInfo roomInfo : roomInfoList) {
            //取出 room_info 房间编号放入list
            listRoomNum.add(roomInfo.getRoomNum());
        }
//        System.out.println("房间编号: "+listRoomNum);
        //2.查询 room 表 条件: 酒店id room_info当中查询出的房间编号依次查询
        List<Integer> listTemp = new ArrayList<>();
        for (Object roomNum : listRoomNum) {
            QueryWrapper<Room> qw1 = new QueryWrapper<>();
            qw1.eq("hotel_id",hotelId);
            qw1.eq("room_num",roomNum);
            Room room = roomMapper.selectOne(qw1);
            listTemp.add(room.getRoomTypeId());
        }
        System.out.println("封装完成对象: "+listTemp);
        //3.对 roomList 进行房间类型的统计 封装成 Map(房间类型id,房间数量)
        Map<Integer,Integer> roomListNumMap = new HashMap<>();
        for (Integer typeId : listTemp) {
//            System.out.println("查询出数据: "+typeId);
            if (roomListNumMap.get(typeId) == null){
                roomListNumMap.put(typeId,1);
            }else {
                roomListNumMap.put(typeId,roomListNumMap.get(typeId)+1);
            }
        }
        System.out.println("封装后的map: "+roomListNumMap);
        //4.根据查询出来的房间类型id 修改 room_left_num 的剩余房间数量
        for (Map.Entry<Integer, Integer> entry : roomListNumMap.entrySet()) {
            QueryWrapper<RoomList> qw2 = new QueryWrapper<>();
            qw2.eq("room_type_id",entry.getKey());
            RoomList roomList = roomListMapper.selectOne(qw2);
            roomList.setRoomLeftNum(entry.getValue());
//            System.out.println("查询出的对象: "+roomList);
            roomListMapper.updateById(roomList);
        }
        QueryWrapper<RoomList> qw3 = new QueryWrapper<>();
        qw3.eq("hotel_id",hotelId);
        List<RoomList> roomLists = roomListMapper.selectList(qw3);
//        System.out.println("查询出对象: "+roomLists);
        return roomLists;
    }

    /**
     * 按照日期查询剩余房间数量
     * 1.查询 room 表中的房间编号 条件： 酒店id 入住状态不为1
     * 2.房间详情表 room_info 按照入住日期 离开日期 酒店id进行查询
     * 3.1和2产生的list进行对比 按照房间编号进行匹配 保存出相同的
     * 4.将完全相同的可以入住的房间编号作为查询条件去查询房间类型(统计房间类型数量)
     * 5.遍历map 将key作为查询条件去修改房间数量
     * 6.重新查询 roomlist
     * @param startTime 入住时间
     * @param endTime 离开时间
     * @param hotelId 酒店id
     * @return
     */
    @Override
    public List<RoomList> selectHotelToRoomListTimeSearch(LocalDateTime startTime, LocalDateTime endTime, int hotelId) {
        //1.查询 room 表中的房间编号 条件： 酒店id 入住状态不为1
        QueryWrapper<Room> qw1 = new QueryWrapper<>();
        qw1.eq("hotel_id",hotelId);
        qw1.eq("room_status",0);
        List<Room> rooms = roomMapper.selectList(qw1);
        System.out.println("查询出所有房间: "+rooms);
        //2.房间详情表 room_info 按照入住日期 离开日期 酒店id进行查询
        QueryWrapper<RoomInfo> qw = new QueryWrapper<>();
        qw.eq("hotel_id",hotelId);
        qw.lt("in_time",startTime);
        qw.lt("out_time",startTime);
        qw.or().gt("in_time",endTime).gt("out_time",endTime);
        List<RoomInfo> roomInfos = roomInfoMapper.selectList(qw);
        System.out.println("查询出所有居住情况: "+roomInfos);
        //3.1和2产生的list进行对比 按照房间编号进行匹配 保存出相同的
        List<Object> list = new ArrayList<>();
        for (int i = 0; i < rooms.size(); i++) {
            for (int j = 0; j < roomInfos.size(); j++) {
                System.out.println("正在执行...");
                System.out.println("rooms==>"+rooms.get(i).getRoomNum());
                System.out.println("roomInfos==>"+roomInfos.get(j).getRoomNum());
                if (rooms.get(i).getRoomNum().equals(roomInfos.get(j).getRoomNum())){
                    System.out.println("完全相同的房间号:"+rooms.get(i).getRoomNum());
                    list.add(rooms.get(i).getRoomNum());
                }
            }
        }
        System.out.println("查询集合:"+list);
        //4.将完全相同的可以入住的房间编号作为查询条件去查询房间类型(统计房间类型数量)
        Map<Object, Integer> map = new HashMap<>();
        QueryWrapper<RoomInfo> qw2 = new QueryWrapper<>();
        for (Object roomNum : list) {
            qw2.clear();
            System.out.println("条件遍历:"+roomNum);
            qw2.eq("room_num",roomNum);
            qw2.eq("hotel_id",hotelId);
            RoomInfo roomInfo = roomInfoMapper.selectOne(qw2);
            System.out.println("查询出满足条件的对象:"+roomInfo);
            if (map.get(roomInfo.getRoomTypeId()) == null){
                map.put(roomInfo.getRoomTypeId(),1);
            }else {
                map.put(roomInfo.getRoomTypeId(),map.get(roomInfo.getRoomTypeId())+1);
            }
        }
        System.out.println("查看map:"+map);
        //5.遍历map 将key作为查询条件去修改房间数量
        QueryWrapper<RoomList> qw3 = new QueryWrapper<>();
        for (Map.Entry<Object, Integer> entry : map.entrySet()) {
            System.out.println("正在执行最后操作....");
            qw3.eq("room_type_id",entry.getKey());
            qw3.eq("hotel_id",hotelId);
            RoomList roomList = roomListMapper.selectOne(qw3);
            roomList.setRoomLeftNum(entry.getValue());
            roomListMapper.updateById(roomList);
        }
        QueryWrapper<RoomList> qw4 = new QueryWrapper<>();
        qw4.eq("hotel_id",hotelId);
        List<RoomList> roomLists = roomListMapper.selectList(qw4);
        return roomLists;
    }

    /**
     * 按照酒店id查询出当前酒店所有评论信息
     * @param hotelId
     */
    @Override
    public ResultVo<List<CommentMongoDB>> getCommentByHotelId(String hotelId) {
        //即时更新mongoDB数据
        setCommentInformation();
        //System.out.println("执行按照id查询");
        //mongoDB根据酒店id查询出所有评论内容
        Query query = new Query(Criteria.where("hotelId").is(hotelId).and("isVisible").is(1));
        List<CommentMongoDB> commentMongoDBS = mongoTemplate.find(query, CommentMongoDB.class);
        System.out.println("---------------->"+commentMongoDBS);
        ResultVo<List<CommentMongoDB>> resultVo = ResultUtils.success(ResultMsg.SUCCESS_MSG, StatusCode.SUCCESS_CODE, commentMongoDBS);
        return resultVo;
    }

    @Override
    public Boolean setCommentInformation() {
        List<CommentMongoDB> commentMongoDBList = mongoTemplate.findAll(CommentMongoDB.class);
        for (CommentMongoDB commentMongoDB : commentMongoDBList) {
            //1.根据userid查询用户信息
            CustomerUser customerUser = customerUserService.getById(commentMongoDB.getUserId());
            //2.修改mongoDB
            Query query = new Query(Criteria.where("_id").is(commentMongoDB.getId()));
            Update update = new Update();
            update.set("userName",customerUser.getUserNickName());
            update.set("userPhoto",customerUser.getStandby02());
            mongoTemplate.updateFirst(query, update, CommentMongoDB.class);
        }
        return true;
    }

    @Override
    public ResultVo<CommentMongoDB> getCommentByOrderId(String orderId) {
        Query query = new Query(Criteria.where("orderId").is(orderId).and("isVisible").is(1));
        CommentMongoDB comment = mongoTemplate.findOne(query, CommentMongoDB.class);
        ResultVo<CommentMongoDB> resultVo = ResultUtils.success(ResultMsg.SUCCESS_MSG, StatusCode.SUCCESS_CODE, comment);
        return resultVo;
    }

    /**
     * 加载所有房间数据到redis当中
     * @return 是否添加成功
     */
    @Override
    public boolean roomListSaveRedis() {
        List<RoomList> roomLists = roomListMapper.selectList(null);
        for (RoomList roomList : roomLists) {
            redisTemplate.opsForSet().add("roomList:"+roomList.getRoomTypeId(), roomList.getRoomLeftNum());
        }
        return true;
    }

    /**
     * 用户点击预定房间的时候对redis进行添加分布式锁操作
     * @param roomTypeId
     */
    @Override
    public void roomListLessInventory(Integer roomTypeId) {
        String key = "roomList:"+roomTypeId;
        String uuid = UUID.randomUUID().toString();
        Boolean isLock = redisTemplate.opsForValue().setIfAbsent(key, uuid, 100, TimeUnit.SECONDS);
    }

    @Override
    public List<RoomList> getRoomListByRoomTypeId(Map map) {
        return null;
    }

    @Override
    public RoomList getById(String id,String num) {
        RoomList roomList = roomListMapper.selectById(id);
        roomList.setRoomLeftNum(Integer.valueOf(num));
        return roomList;
    }

}

